home *** CD-ROM | disk | FTP | other *** search
/ BBS Toolkit / BBS Toolkit.iso / rbbs_pc / aed243a.zip / AED243.BAS < prev    next >
BASIC Source File  |  1990-06-10  |  46KB  |  1,439 lines

  1. '*
  2. '*  ANSIED v2.43a
  3. '*---------------------------------------------------------------------------
  4. '*  Full Screen Text Editor for RBBS-PC
  5. '*  QuickBASIC v4.5 Standalone Version
  6. '*  06-10-90
  7. '*
  8. '*  v2.1xx ... made it work with RBBS v17
  9. '*  v2.2 ... fixed some inconsistincies in the code as to # of lines in msg.
  10. '*           Some of the code thought 99 was length, some thought 100.
  11. '*  v2.3 .. let it work with quoted reply.  No more REDIM of ZOutTxt$
  12. '*  v2.4 .. removed tabs, margins code to be smaller
  13. '*  v2.41.. fixed bug with loss of bold attribute occasionally
  14. '*  v2.42.. made it work as a v17.3 subroutine.  Added block delete.
  15. '*  v2.43.. Added to: and from:.  Made cursor keys work locally.
  16. '*  v2.43a.... Stupid little bugs fixed
  17. '*
  18. '*  Returns:
  19. '*  ZSubParm  =  1 - Save Message
  20. '*            =  2 - Abort Message
  21. '*            = -1 - Dropped Carrier
  22. '*            = -2 - Sleep Disconnect
  23. '*
  24. '* Compile with:
  25. '*   BC C:\RBBSARCS\AED243.BAS /O/T/C:512;
  26. '*
  27.  
  28. DECLARE SUB Ansied (T$, S$, L%)
  29. DECLARE SUB ClearScreen ()
  30. DECLARE SUB UpdateStatusLine (How%)
  31. DECLARE SUB MoveCursor (NewRow%, NewCol%)
  32. DECLARE SUB UnString (WasL$, BadString$)
  33. DECLARE SUB UpdateScreen ()
  34. DECLARE SUB Getch (YY$)
  35. DECLARE SUB SaveCursor (Row%, Col%)
  36. DECLARE SUB DisplayMainMenu ()
  37. DECLARE SUB ClearMainMenu ()
  38. DECLARE SUB PutScreen (YY$, Colour%, Bold%)
  39. DECLARE SUB ExecuteMainMenuCommand (CMD$)
  40. DECLARE SUB DeleteCurrentLine (Index%)
  41. DECLARE SUB BackspChar ()
  42. DECLARE SUB CarrRetKey ()
  43. DECLARE SUB NormalChar (YY$)
  44. DECLARE SUB EraseToEOL (LineNumber%, ColNumber%)
  45. DECLARE SUB FindWrap (YY$, WhereToWrap%)
  46. DECLARE SUB Ungetch (X%)
  47. DECLARE SUB DoneWithMsg ()
  48. DECLARE SUB HelpMe ()
  49. DECLARE SUB ReformText (Justify%)
  50. DECLARE SUB LastParaLine (I%, LastLine%, Result%)
  51. DECLARE SUB RightTrim (YY$)
  52.  
  53. DECLARE SUB NameCaps (YY$)
  54. DECLARE SUB Carrier ()
  55. DECLARE SUB QuickTput (YY$, NumReturns%)
  56. DECLARE SUB Tput ()
  57. DECLARE SUB FindFKey ()
  58. DECLARE SUB GetCom (YY$)
  59. DECLARE SUB UpdtCalr (YY$, Z%)
  60. DECLARE SUB EofComm (Char%)
  61. DECLARE SUB BufFile (Filename$, Z%)
  62. DECLARE SUB CheckTime (LogoffTime!, Remain!, Z%)
  63. DECLARE SUB Line25 ()
  64. DECLARE SUB ColorPrompt (YY$)
  65.  
  66. ' $INCLUDE: 'RBBS-VAR.MOD'
  67.  
  68. 100   CONST ColorRset = 0
  69.       CONST RedFore = 31
  70.       CONST GreenFore = 32
  71.       CONST YellowFore = 33
  72.       CONST BlueFore = 34
  73.       CONST MagentaFore = 35
  74.       CONST CyanFore = 36
  75.       CONST WhiteFore = 37
  76.       CONST BlueBack = 44
  77.  
  78. 110   CONST ESCKey = 27
  79.       CONST BackspKey = 8
  80.       CONST OtherBackspKey = 127
  81.       CONST CarrRet = 13
  82.       CONST ReformTextKey = 2    ' Ctrl-B
  83.       CONST EndSessionKey = 11   ' Ctrl-K
  84.       CONST HelpKey = 14         ' Ctrl-N
  85.       CONST ReflowTextKey = 15   ' Ctrl-O
  86.       CONST RepaintKey = 16      ' Ctrl-P
  87.       CONST ToggleINSKey = 22    ' Ctrl-V
  88.       CONST LineUpKey = 5        ' Ctrl-E
  89.       CONST LineDownKey = 24     ' Ctrl-X
  90.       CONST ColLeftKey = 19      ' Ctrl-S
  91.       CONST ColRightKey = 4      ' Ctrl-D
  92.       CONST WordLeftKey = 1      ' Ctrl-A
  93.       CONST WordRightKey = 6     ' Ctrl-F
  94.       CONST PageUpKey = 18       ' Ctrl-R
  95.       CONST PageDownKey = 3      ' Ctrl-C
  96.       CONST HomeKey = 23         ' Ctrl-W
  97.       CONST EndKey = 26          ' Ctrl-Z
  98.       CONST LineDeleteKey = 25   ' Ctrl-Y
  99.       CONST CharDeleteKey = 7    ' Ctrl-G
  100.  
  101.       CONST BlankLine$ = ""
  102. 119   CONST Version$ = "v2.43a"
  103.  
  104.       DEFINT A-Z
  105.  
  106. 120   COMMON SHARED /Ansied/ CurrentRow, CurrentCol, TopLine
  107.       COMMON SHARED /Ansied/ OldColour, IsBold, InsertMode
  108.       COMMON SHARED /Ansied/ SoftSpace$, InsOvwPosition
  109.       COMMON SHARED /Ansied/ BlockDelActive, MsgLockLines
  110.       COMMON SHARED /Ansied/ BlockLine1, BlockLine2
  111.       COMMON SHARED /Ansied/ MsgTo$, MsgSubj$
  112.  
  113.       '*
  114.       '* Standalone Main Program
  115.       '*
  116.       DIM ZOutTxt$(100)
  117.  
  118.       ZFalse = 0
  119.       ZTrue = NOT ZFalse
  120.       ZEmphasizeOff$ = ""
  121.       ZLocalUser = ZTrue
  122.       ZLinesInMsg = 56
  123.       ZRightMargin = 40
  124.       ZMaxMsgLines = 60
  125.       FOR I = 4 TO ZLinesInMsg
  126.          ZOutTxt$(I) = "> This is line number" + STR$(I)
  127.       NEXT
  128.       ZOutTxt$(1) = "* Locked Message Line 1 *"
  129.       ZOutTxt$(2) = "* Locked Message Line 2 *"
  130.       CALL Ansied("Mike Zakharoff", "(R)New Fullscreen Editor", 2)
  131.       END
  132.  
  133. '*  AnsiEd
  134. '*----------------------------------------------------------------------------
  135. '*  Main full-screen editor routine
  136. '*
  137. '*
  138.       SUB Ansied (T$, S$, L%) STATIC
  139.  
  140.       '*
  141.       '* ZworkAra$() holds what's currently on the user's screen.
  142.       '* 24 Lines: ZWorkAra$(1) = Menu, Bottom Line = "Line 25"
  143.       '*
  144. 500   REDIM ZWorkAra$(24)
  145.       '*
  146.       '* TopLine is the index into the ZOutTxt$() array that
  147.       '* corresponds to the top of the displayed image, i.e.
  148.       '* what's on line 2 of the user's screen.
  149.       '*
  150.       '*   1,12,23,34,45,56,78
  151.       '*
  152.       TopLine = 1
  153.       SoftSpace$ = CHR$(250)
  154.       InsertMode = ZTrue
  155.       ZLineFeed$ = CHR$(10)
  156.       OldColour = 0
  157.       Bold = ZFalse
  158.       IsBold = 99
  159.       BlockDelActive = ZFalse
  160.       CurrentCol = 0
  161.       CurrentRow = 0
  162.  
  163.       MsgLockLines = L
  164.  
  165.       MsgTo$ = T$
  166.       CALL NameCaps(MsgTo$)
  167.  
  168.       MsgSubj$ = S$
  169.       ZOutTxt$ = ""
  170.       IF LEFT$(MsgSubj$, 3) = "(R)" THEN
  171.          ZOutTxt$ = "(R)"
  172.          MsgSubj$ = MID$(MsgSubj$, 4)
  173.       END IF
  174.       CALL NameCaps(MsgSubj$)
  175.       MsgSubj$ = ZOutTxt$ + MsgSubj$
  176.  
  177.       '*
  178.       '* Initialize the screen array as all blanks
  179.       '*
  180. 510   FOR I = 3 TO 24
  181.          ZWorkAra$(I) = BlankLine$
  182.       NEXT I
  183.  
  184.       '*
  185.       '* Initialize the screen
  186.       '*
  187.       CALL ClearScreen
  188.       CALL UpdateStatusLine(1)
  189.       CALL MoveCursor(3, 1)
  190.       '*
  191.       '* Remove ANSI sequences from the quoted lines
  192.       '*
  193.       IF ZLinesInMsg > 88 THEN
  194.          ZLinesInMsg = 88
  195.       END IF
  196.       IF ZMaxMsgLines > 98 THEN
  197.          ZMaxMsgLines = 98
  198.       END IF
  199.       IF ZLinesInMsg > ZMaxMsgLines THEN
  200.          ZLinesInMsg = ZMaxMsgLines
  201.       END IF
  202.       FOR I = ZLinesInMsg + 1 TO 99
  203.          ZOutTxt$(I) = BlankLine$
  204.       NEXT
  205.       IF ZLinesInMsg <> 0 THEN
  206.          FOR I = 1 TO ZLinesInMsg
  207.             CALL UnString(ZOutTxt$(I), "")
  208.          NEXT
  209.          I! = ZLinesInMsg / 11
  210.          J = FIX(I!)
  211.          IF J = I! THEN
  212.            J = J - 1
  213.          END IF
  214.          TopLine = J * 11 + 1
  215.          J = ZLinesInMsg - TopLine
  216.          CALL MoveCursor(J + 5, 1)
  217.       END IF
  218.       CALL UpdateScreen
  219.  
  220.       '*
  221.       '* Run the Editor
  222.       '*
  223. 520   WHILE ZTrue
  224.  
  225.          CALL Carrier: GOSUB 740
  226.  
  227.          CALL Getch(B$): GOSUB 740
  228.          KeyPressed = ASC(B$)
  229.  
  230.          Index = CurrentRow + TopLine - 3
  231.  
  232.          IF BlockDelActive OR Index <= MsgLockLines OR Index > ZMaxMsgLines THEN
  233. 530         SELECT CASE KeyPressed
  234.                CASE CarrRet
  235.                   IF BlockDelActive THEN
  236.                      BlockDelActive = ZFalse
  237.                      BlockLine2 = Index
  238.                      IF Index < BlockLine1 THEN
  239.                         BlockLine2 = BlockLine1
  240.                         BlockLine1 = Index
  241.                      END IF
  242.                      IF BlockLine1 <= MsgLockLines THEN
  243.                         BlockLine1 = MsgLockLines + 1
  244.                      END IF
  245.                      IF BlockLine2 > ZMaxMsgLines THEN
  246.                         BlockLine2 = ZMaxMsgLines
  247.                      END IF
  248.                      K = 0
  249.                      FOR I = BlockLine2 + 1 TO 99
  250.                         ZOutTxt$(BlockLine1 + K) = ZOutTxt$(I)
  251.                         K = K + 1
  252.                      NEXT I
  253.                      WHILE BlockLine1 + K <= 99
  254.                         ZOutTxt$(BlockLine1 + K) = BlankLine$
  255.                         K = K + 1
  256.                      WEND
  257.                      CALL UpdateScreen
  258.                      CALL UpdateStatusLine(2)
  259.                      CALL MoveCursor(RowSave, ColSave)
  260.                   END IF
  261.                   KeyPressed = 255
  262.  
  263. 540            CASE ESCKey
  264.                   IF BlockDelActive THEN
  265.                      BlockDelActive = ZFalse
  266.                      CALL SaveCursor(RowSave, ColSave)
  267.                      CALL UpdateStatusLine(2)
  268.                      CALL MoveCursor(RowSave, ColSave)
  269.                      KeyPressed = 255
  270.                   END IF
  271.  
  272.                CASE LineUpKey, LineDownKey, PageDownKey, PageUpKey
  273.                   '*
  274.                   '* Up and Down get passed on
  275.                   '*
  276.                CASE ELSE
  277.                   '*
  278.                   '* Ignore the key
  279.                   '*
  280.                   KeyPressed = 255
  281.  
  282.             END SELECT
  283.          END IF
  284.  
  285.          '*
  286.          '* Look for an ANSI escape sequence after an ESC
  287.          '*
  288. 550      IF KeyPressed = ESCKey THEN
  289.             CALL Getch(B$): GOSUB 740
  290.             IF B$ = "[" THEN                    ' ANSI sequence
  291.                CALL Getch(B$): GOSUB 740
  292.                IF B$ = "C" THEN
  293.                   KeyPressed = ColRightKey
  294.                ELSEIF B$ = "D" THEN
  295.                   KeyPressed = ColLeftKey
  296.                ELSEIF B$ = "A" THEN
  297.                   KeyPressed = LineUpKey
  298.                ELSEIF B$ = "B" THEN
  299.                   KeyPressed = LineDownKey
  300.                END IF
  301.             END IF
  302.          END IF
  303.  
  304. 560      SELECT CASE KeyPressed
  305.             CASE ESCKey
  306.                '*
  307.                '* User wants to see main menu
  308.                '*
  309.                CALL SaveCursor(RowSave, ColSave)
  310.                CALL DisplayMainMenu
  311.                CALL MoveCursor(RowSave, ColSave)
  312.                KeyPressed = 255: B$ = ""
  313.                WHILE KeyPressed <> ESCKey
  314.                   CALL Getch(B$): GOSUB 740
  315.                   B$ = UCASE$(B$)
  316.                   KeyPressed = ASC(B$)
  317.                   IF KeyPressed = CarrRet THEN
  318.                      B$ = "H"
  319.                   END IF
  320.                   I = INSTR("HJREIPB" + CHR$(ESCKey), B$)
  321.                   IF I = 7 THEN
  322.                      BlockDelActive = ZTrue
  323.                      BlockLine1 = RowSave + TopLine - 3
  324.                      CALL ClearMainMenu
  325.                      CALL QuickTput(ZEmphasizeOff$, 0)
  326.                      CALL PutScreen("Block Delete: Move cursor to last line to delete and press ENTER   ESC Quits", 99, ZFalse)
  327.                      CALL MoveCursor(RowSave, ColSave)
  328.                      BlockLine2 = 0
  329.                      KeyPressed = ESCKey
  330.                   ELSEIF I <> 0 THEN
  331.                      CALL ExecuteMainMenuCommand(B$): GOSUB 740
  332.                      KeyPressed = ESCKey
  333.                   END IF
  334.                WEND
  335.                CALL MoveCursor(RowSave, ColSave)
  336.  
  337. 570         CASE LineUpKey
  338.                '*
  339.                '* Move the current cursor position up one line
  340.                '*
  341.                IF CurrentRow > 3 THEN
  342.                   CALL MoveCursor(CurrentRow - 1, CurrentCol)
  343.                ELSE
  344.                   IF TopLine <> 1 THEN
  345.                      TopLine = TopLine - 11
  346.                      CALL MoveCursor(CurrentRow + 10, CurrentCol)
  347.                      CALL UpdateScreen
  348.                   END IF
  349.                END IF
  350.  
  351. 580         CASE LineDownKey
  352.                '*
  353.                '* Move the current cursor position down one line
  354.                '*
  355.                IF CurrentRow < 24 THEN
  356.                   CALL MoveCursor(CurrentRow + 1, CurrentCol)
  357.                ELSE
  358.                   IF NOT TopLine = 78 THEN
  359.                      TopLine = TopLine + 11
  360.                      CALL MoveCursor(CurrentRow - 10, CurrentCol)
  361.                      CALL UpdateScreen
  362.                   END IF
  363.                END IF
  364.  
  365. 590         CASE ColLeftKey
  366.                '*
  367.                '* Move the current cursor left one column
  368.                '*
  369.                IF CurrentCol > 1 THEN
  370.                   CALL MoveCursor(CurrentRow, CurrentCol - 1)
  371.                END IF
  372.  
  373. 600         CASE ColRightKey
  374.                '*
  375.                '* Move the current cursor right one column
  376.                '*
  377.                IF CurrentCol < 79 THEN
  378.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  379.                END IF
  380.  
  381. 610         CASE WordRightKey
  382.                '*
  383.                '* Move the current cursor right one word
  384.                '*
  385.                FOR I = CurrentCol TO LEN(ZOutTxt$(Index)) - 1
  386.                   YY$ = MID$(ZOutTxt$(Index), I, 1)
  387.                   ZZ$ = MID$(ZOutTxt$(Index), I + 1, 1)
  388.                   IF (YY$ = " " OR YY$ = SoftSpace$) AND ZZ$ <> " " AND ZZ$ <> SoftSpace$ THEN
  389.                      NewCol = I + 1
  390.                      IF NewCol > 79 THEN
  391.                         NewCol = 79
  392.                      END IF
  393.                      CALL MoveCursor(CurrentRow, NewCol)
  394.                      EXIT FOR
  395.                   END IF
  396.                NEXT I
  397.  
  398. 620         CASE WordLeftKey
  399.                '*
  400.                '* Move the current cursor left one word
  401.                '*
  402.                Found = ZFalse
  403.                FOR I = CurrentCol - 1 TO 2 STEP -1
  404.                   ZZ$ = MID$(ZOutTxt$(Index), I, 1)
  405.                   YY$ = MID$(ZOutTxt$(Index), I - 1, 1)
  406.                   IF (YY$ = " " OR YY$ = SoftSpace$) AND ZZ$ <> " " AND ZZ$ <> SoftSpace$ THEN
  407.                      NewCol = I
  408.                      CALL MoveCursor(CurrentRow, NewCol)
  409.                      Found = ZTrue
  410.                      EXIT FOR
  411.                   END IF
  412.                NEXT I
  413.                IF NOT Found THEN
  414.                   CALL MoveCursor(CurrentRow, 1)
  415.                END IF
  416.  
  417. 630         CASE HomeKey
  418.                '*
  419.                '* Move cursor to the start of the line
  420.                '*
  421.                CALL MoveCursor(CurrentRow, 1)
  422.  
  423. 640         CASE EndKey
  424.                '*
  425.                '* Move cursor to the end of the line
  426.                '*
  427.                IF ZOutTxt$(Index) = STRING$(79, 250) THEN
  428.                   NewCol = 1
  429.                ELSE
  430.                   NewCol = 0
  431.                   FOR I = LEN(ZOutTxt$(Index)) TO 1 STEP -1
  432.                      IF MID$(ZOutTxt$(Index), I, 1) <> SoftSpace$ THEN
  433.                         NewCol = I + 1
  434.                         EXIT FOR
  435.                      END IF
  436.                   NEXT I
  437.                   IF NewCol > 79 THEN
  438.                      NewCol = 79
  439.                   ELSEIF NewCol < 1 THEN
  440.                      NewCol = 1
  441.                   END IF
  442.                END IF
  443.                CALL MoveCursor(CurrentRow, NewCol)
  444.  
  445. 650         CASE PageDownKey
  446.                '*
  447.                '* Move the display one page down
  448.                '*
  449.                TopLine = TopLine + 22
  450.                IF TopLine > 78 THEN
  451.                   TopLine = 78
  452.                END IF
  453.                CALL UpdateScreen
  454.  
  455. 660         CASE PageUpKey
  456.                '*
  457.                '* Move the display one page up
  458.                '*
  459.                TopLine = TopLine - 22
  460.                IF TopLine < 1 THEN
  461.                   TopLine = 1
  462.                END IF
  463.                CALL UpdateScreen
  464.  
  465. 670         CASE LineDeleteKey
  466.                '*
  467.                '* Delete the current line in the file
  468.                '*
  469.                CALL SaveCursor(RowSave, ColSave)
  470.                CALL DeleteCurrentLine(Index)
  471.                CALL MoveCursor(RowSave, ColSave)
  472.  
  473. 680         CASE CharDeleteKey
  474.                '*
  475.                '* Delete the current character
  476.                '*
  477.                IF CurrentCol <= LEN(ZOutTxt$(Index)) THEN
  478.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  479.                   CALL BackspChar
  480.                END IF
  481.  
  482. 690         CASE BackspKey, OtherBackspKey
  483.                '*
  484.                '* Back up one character and destroy it
  485.                '*
  486.                CALL BackspChar
  487.  
  488. 700         CASE CarrRet
  489.                '*
  490.                '* Move to the next line, left column
  491.                '*
  492.                IF NOT Index >= ZMaxMsgLines THEN
  493.                   CALL CarrRetKey
  494.                END IF
  495.  
  496. 710         CASE HelpKey, ReformTextKey, ReflowTextKey, EndSessionKey, ToggleINSKey, RepaintKey
  497.                '*
  498.                '* Execute a main menu command
  499.                '*
  500.                '*          1234567890123456789012
  501.                YY$ = MID$(" J        E  HRP     I", KeyPressed, 1)
  502.                CALL SaveCursor(RowSave, ColSave)
  503.                CALL ExecuteMainMenuCommand(YY$): GOSUB 740
  504.                CALL MoveCursor(RowSave, ColSave)
  505.  
  506.             CASE IS > 127, IS < 32
  507.                '*
  508.                '* Ignore characters above 127 or below 32
  509.                '*
  510. 720         CASE ELSE
  511.                '*
  512.                '* Input was a normal character
  513.                '*
  514.                CALL NormalChar(B$)
  515.  
  516.          END SELECT
  517.       WEND
  518.  
  519. 730   REDIM ZWorkAra$(13)
  520.       EXIT SUB
  521.  
  522.       '*
  523.       '* Test ZSubParam and Exit ANSIED if the carrier dropped
  524.       '*
  525. 740   IF ZSubParm <> 0 THEN
  526.          GOTO 730
  527.       END IF
  528.       RETURN
  529.  
  530.       END SUB         ' Sub AnsiEd
  531.  
  532. '*  BackspChar()
  533. '*----------------------------------------------------------------------------
  534. '*  This routine handles the user entering the backspace key
  535. '*
  536. '*
  537.       SUB BackspChar STATIC
  538. 1200  CALL SaveCursor(RowSave, ColSave)
  539.       Index = TopLine + CurrentRow - 3
  540.       IF Index = MsgLockLines + 1 AND CurrentCol = 1 THEN
  541.          EXIT SUB
  542.       END IF
  543.       AtEndOfLine = CurrentCol > LEN(ZOutTxt$(Index))
  544. 1210  IF CurrentCol > 1 THEN
  545.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 2) + MID$(ZOutTxt$(Index), CurrentCol)
  546.          CALL EraseToEOL(CurrentRow, CurrentCol - 1)
  547.          IF NOT AtEndOfLine THEN
  548.             YY$ = MID$(ZOutTxt$(Index), ColSave - 1)
  549.             CALL MoveCursor(RowSave, ColSave - 1)
  550.             CALL PutScreen(YY$, YellowFore, ZTrue)
  551.          END IF
  552.          CALL MoveCursor(RowSave, ColSave - 1)
  553.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  554.       ELSEIF LEN(ZOutTxt$(Index - 1)) >= ZRightMargin THEN
  555.          '*
  556.          '* Do nothing
  557.          '*
  558. 1220  ELSE
  559.          NewCol = LEN(ZOutTxt$(Index - 1)) + 1
  560.          YY$ = ZOutTxt$(Index)
  561.          CALL UnString(YY$, SoftSpace$)
  562.          ZOutTxt$(Index - 1) = ZOutTxt$(Index - 1) + YY$
  563.          IF LEN(ZOutTxt$(Index - 1)) < ZRightMargin THEN
  564.             CALL DeleteCurrentLine(Index)
  565. 1230     ELSE
  566.             CALL FindWrap(LEFT$(ZOutTxt$(Index - 1), ZRightMargin + 1), I)
  567.             IF I = 0 OR I = 1 THEN
  568.                I = ZRightMargin
  569.             END IF
  570.             ZOutTxt$(Index) = MID$(ZOutTxt$(Index - 1), I + 1)
  571.             ZOutTxt$(Index - 1) = LEFT$(ZOutTxt$(Index - 1), I)
  572.          END IF
  573.          IF RowSave > 3 THEN
  574.             CALL MoveCursor(RowSave - 1, NewCol)
  575.             CALL UpdateScreen
  576.          ELSE
  577.             CALL MoveCursor(RowSave, NewCol)
  578.             CALL Ungetch(LineUpKey)
  579.          END IF
  580.       END IF
  581.       END SUB
  582.  
  583.       SUB BufFile (Filename$, Z) STATIC
  584.       END SUB
  585.  
  586.       SUB Carrier STATIC
  587.       ZSubParm = 0
  588.       END SUB
  589.  
  590. '*  CarrRetKey()
  591. '*----------------------------------------------------------------------------
  592. '*  This routine handles carriage returns entered in the file
  593. '*
  594. '*
  595.       SUB CarrRetKey STATIC
  596. 1300  Index = CurrentRow + TopLine - 3
  597.       IF Index >= 99 THEN
  598.          EXIT SUB
  599.       END IF
  600.       IF InsertMode THEN         ' Insert a new line
  601.          FOR I = 98 TO Index + 1 STEP -1
  602.             ZOutTxt$(I + 1) = ZOutTxt$(I)
  603.          NEXT I
  604.          IF LEN(ZOutTxt$(Index)) >= CurrentCol THEN
  605.             ZOutTxt$(Index + 1) = MID$(ZOutTxt$(Index), CurrentCol)
  606.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1)
  607.          ELSE
  608.             ZOutTxt$(Index + 1) = BlankLine$
  609.          END IF
  610.          CALL UpdateScreen
  611.       END IF
  612.       IF CurrentRow < 24 THEN
  613.          CALL MoveCursor(CurrentRow + 1, 1)
  614.       ELSE
  615.          CALL MoveCursor(CurrentRow, 1)
  616.          CALL Ungetch(LineDownKey)
  617.       END IF
  618.       END SUB
  619.  
  620.       SUB CheckTime (LogoffTime!, Remain!, Z) STATIC
  621.       Remain! = 1
  622.       END SUB
  623.  
  624. '*  ClearMainMenu()
  625. '*----------------------------------------------------------------------------
  626. '*  This routine clears the main menu from the top line
  627. '*
  628. '*
  629.       SUB ClearMainMenu STATIC
  630. 1400  CALL EraseToEOL(1, 1)
  631.       CALL MoveCursor(1, 1)
  632.       END SUB
  633.  
  634. '*  ClearScreen()
  635. '*----------------------------------------------------------------------------
  636. '*  This routine clears the screen and moves the cursor to row 2, col 1
  637. '*
  638. '*
  639.       SUB ClearScreen STATIC
  640. 1500  FOR I = 1 TO 23
  641.          ZWorkAra$(I) = BlankLine$
  642.       NEXT I
  643.       CALL QuickTput("H", 0)  ' clear screen, column 1, row 3
  644.       ZSubParm = 2
  645.       CALL Line25
  646.       ZSubParm = 0
  647.       CurrentCol = 1
  648.       CurrentRow = 3
  649.       IsBold = 99
  650.       END SUB
  651.  
  652.       SUB ColorPrompt (YY$)
  653.       CALL QuickTput(ZEmphasizeOff$, 0)
  654.       END SUB
  655.  
  656. '*  DeleteCurrentLine()
  657. '*----------------------------------------------------------------------------
  658. '*  This routine deletes the current line on the screen and in the array
  659. '*  ZOutTxt$, and moves the next lower line up one  It then repaints the
  660. '*  affected portion of the screen (from the deleted line down)
  661. '*
  662. '*
  663.       SUB DeleteCurrentLine (Index%) STATIC
  664. 1600  FOR I = Index% TO 98
  665.          ZOutTxt$(I) = ZOutTxt$(I + 1)
  666.       NEXT I
  667.       ZOutTxt$(99) = BlankLine$
  668.       CALL UpdateScreen
  669.       END SUB
  670.  
  671. '*  DisplayMainMenu()
  672. '*----------------------------------------------------------------------------
  673. '*  This routine displays the main menu on the top line
  674. '*
  675. '*
  676.       SUB DisplayMainMenu STATIC
  677. 1700  CALL MoveCursor(1, 1)
  678.       CALL QuickTput(ZEmphasizeOff$, 0)
  679.       YY$ = " [H]elp  E)nd  R)eflow  J)ustify  I)ns/Ovw  P)aint  B)lock Delete   ESC Quits"
  680.       YY$ = YY$ + SPACE$(79 - LEN(YY$))
  681.       ZHiLiteOff = ZFalse
  682.       CALL ColorPrompt(YY$)
  683.       CALL PutScreen(YY$, 99, ZTrue)
  684.       IsBold = 99
  685.       END SUB
  686.  
  687. '*  DoneWithMsg()
  688. '*----------------------------------------------------------------------------
  689. '*  This routine is called to save or abort the message
  690. '*
  691. '*
  692.       SUB DoneWithMsg STATIC
  693. 1800  CALL SaveCursor(RowSave, ColSave)
  694.       CALL ClearMainMenu
  695.       CALL QuickTput(ZEmphasizeOff$, 0)
  696.       YY$ = "End Message: S)ave, A)bort, or [C]ontinue? "
  697.       ZHiLiteOff = ZFalse
  698.       CALL ColorPrompt(YY$)
  699.       CALL PutScreen(YY$, 99, ZTrue)
  700.       B$ = " "
  701.       WHILE INSTR("SAC" + CHR$(ESCKey) + CHR$(CarrRet), B$) = 0
  702.          CALL Getch(B$)
  703.          IF ZSubParm <> 0 THEN
  704.             EXIT SUB
  705.          END IF
  706.          B$ = UCASE$(B$)
  707.       WEND
  708. 1810  SELECT CASE B$
  709.          CASE "S"        ' Save Message
  710.             CALL ClearScreen
  711.             '*
  712.             '* Remove trailing blank lines from the message
  713.             '*
  714.             EndOfMsg = ZMaxMsgLines
  715.             FOR I = ZMaxMsgLines TO 1 STEP -1
  716.                IF ZOutTxt$(I) <> BlankLine$ THEN
  717.                   EndOfMsg = I
  718.                   EXIT FOR
  719.                END IF
  720.             NEXT I
  721.             IF I = 0 THEN
  722.                EndOfMsg = 1
  723.             END IF
  724.             FOR I = 1 TO EndOfMsg
  725.                J = INSTR(ZOutTxt$(I), SoftSpace$)
  726.                WHILE J <> 0
  727.                   MID$(ZOutTxt$(I), J, 1) = " "
  728.                   J = INSTR(ZOutTxt$(I), SoftSpace$)
  729.                WEND
  730.             NEXT I
  731.             FOR I = EndOfMsg TO 1 STEP -1
  732.                ZOutTxt$ = RTRIM$(ZOutTxt$)
  733.                IF ZOutTxt$(I) <> BlankLine$ THEN
  734.                   EndOfMsg = I
  735.                   EXIT FOR
  736.                END IF
  737.             NEXT I
  738.             ZLinesInMsg = EndOfMsg
  739.             CALL QuickTput(ZEmphasizeOff$, 0)
  740.             ZSubParm = 1
  741.  
  742. 1820     CASE "A"
  743.             CALL ClearMainMenu
  744.             CALL QuickTput(ZEmphasizeOff$, 0)
  745.             YY$ = "Abort: Are You Sure (Y)es,[N]o)? "
  746.             ZHiLiteOff = ZFalse
  747.             CALL ColorPrompt(YY$)
  748.             CALL PutScreen(YY$, 99, ZTrue)
  749.             CALL Getch(B$)
  750.             IF ZSubParm <> 0 THEN
  751.                B$ = "Y"
  752.             END IF
  753.             IF UCASE$(B$) = "Y" THEN
  754.                CALL ClearScreen
  755.                CALL QuickTput(ZEmphasizeOff$, 0)
  756.                ZSubParm = 2
  757.             END IF
  758.       END SELECT
  759.       END SUB
  760.  
  761.       SUB EofComm (Char%) STATIC
  762.       Char% = -1
  763.       END SUB
  764.  
  765. '*  EraseToEOL()
  766. '*----------------------------------------------------------------------------
  767. '*  This routine clears from a position to to the end of that line
  768. '*
  769. '*
  770.       SUB EraseToEOL (LineNumber, ColNumber) STATIC
  771. 1900  CALL SaveCursor(RowSave, ColSave)
  772.       CALL MoveCursor(LineNumber, ColNumber)
  773.       CALL QuickTput("", 0)
  774.       CALL MoveCursor(RowSave, ColSave)
  775.       END SUB
  776.  
  777. '*  ExecuteMainMenuCommand()
  778. '*----------------------------------------------------------------------------
  779. '* This routine executes the passed main menu command
  780. '*
  781. '*
  782.       SUB ExecuteMainMenuCommand (CMD$) STATIC
  783. 2000  ZSubParm = 0
  784.       SELECT CASE CMD$
  785.          CASE "H"
  786.             CALL HelpMe
  787.          CASE "E"
  788.             CALL DoneWithMsg
  789.          CASE "P"
  790.             CALL ClearScreen
  791.             CALL UpdateScreen
  792.          CASE "I"
  793.             InsertMode = NOT InsertMode
  794.          CASE "R"
  795.             CALL ReformText(ZFalse)
  796.          CASE "J"
  797.             CALL ReformText(ZTrue)
  798.       END SELECT
  799.       IsBold = 99
  800.       IF ZSubParm = 0 THEN
  801.          CALL ClearMainMenu
  802.          CALL UpdateStatusLine(1)
  803.       END IF
  804.       END SUB
  805.  
  806.       SUB FindFKey
  807.       ZSubParm = 0
  808.       ZKeyPressed$ = ""
  809.       END SUB
  810.  
  811. '*  FindWrap()
  812. '*----------------------------------------------------------------------------
  813. '*  This routine finds a place in the string yy$ that could be used as a
  814. '*  place to wrap the line WhereToWrap should be the last position that
  815. '*  remains in the line, ie
  816. '*    set   currentline$ = left$(yy$,wheretowrap)
  817. '*          nextline$    = mid$ (yy$,wheretowrap+1)
  818. '*
  819. '*
  820.       SUB FindWrap (YY$, WhereToWrap) STATIC
  821. 2100  I = LEN(YY$)
  822.       XX$ = " " + SoftSpace$
  823.       '*
  824.       '* Back over "False hits"
  825.       '*
  826.       ZZ$ = MID$(YY$, I, 1)
  827.       WHILE INSTR(XX$, ZZ$) <> 0 AND I <> 1
  828.          I = I - 1
  829.          ZZ$ = MID$(YY$, I, 1)
  830.       WEND
  831.       WHILE INSTR(XX$, ZZ$) = 0 AND I <> 1
  832.          I = I - 1
  833.          ZZ$ = MID$(YY$, I, 1)
  834.       WEND
  835.       WhereToWrap = I
  836.       END SUB
  837.  
  838. '*  Getch()
  839. '*----------------------------------------------------------------------------
  840. '*  This routine reads a character from the user into YY$
  841. '*
  842. '*
  843.       SUB Getch (YY$) STATIC
  844. 2200  ZAutoLogoff! = TIMER + ZWaitBeforeDisconnect
  845.       CALL Carrier
  846.       YY$ = ""
  847.       WHILE ZSubParm <> -1 AND ZSubParm <> -2 AND YY$ = ""
  848.          ZSubParm = 0
  849.          IF LEN(ZCommportStack$) > 0 THEN
  850.             YY$ = LEFT$(ZCommportStack$, 1)
  851.             ZCommportStack$ = MID$(ZCommportStack$, 2)
  852.          ELSE
  853.             IF ZLocalUser THEN
  854.                YY$ = INKEY$
  855.                IF LEN(YY$) = 2 THEN
  856.                   KeyPressed = ASC(RIGHT$(YY$, 1))
  857.                   YY$ = ""
  858.                   SELECT CASE KeyPressed
  859.                      CASE 82                  ' Insert
  860.                         YY$ = CHR$(ToggleINSKey)
  861.                      CASE 83                  ' Delete
  862.                         YY$ = CHR$(CharDeleteKey)
  863.                      CASE 71                  ' Home
  864.                         YY$ = CHR$(HomeKey)
  865.                      CASE 73                  ' PgUp
  866.                         YY$ = CHR$(PageUpKey)
  867.                      CASE 72                  ' Up Arrow
  868.                         YY$ = CHR$(LineUpKey)
  869.                      CASE 80                  ' Down Arrow
  870.                         YY$ = CHR$(LineDownKey)
  871.                      CASE 81                  ' PgDn
  872.                         YY$ = CHR$(PageDownKey)
  873.                      CASE 75                  ' Left Arrow
  874.                         YY$ = CHR$(ColLeftKey)
  875.                      CASE 77                  ' Right Arrow
  876.                         YY$ = CHR$(ColRightKey)
  877.                      CASE 115                 ' Ctrl-Left Arrow
  878.                         YY$ = CHR$(WordLeftKey)
  879.                      CASE 116                 ' Ctrl-Right Arrow
  880.                         YY$ = CHR$(WordRightKey)
  881.                      CASE 79                  ' End
  882.                         YY$ = CHR$(EndKey)
  883.                   END SELECT
  884.                END IF
  885.             ELSE
  886.                CALL FindFKey
  887.                IF ZSubParm >= 0 THEN
  888.                   YY$ = ZKeyPressed$
  889.                   IF YY$ = "" THEN
  890.                      CALL EofComm(Char%)
  891.                      IF Char% = -1 THEN
  892.                         CALL CheckTime(ZAutoLogoff!, Remain!, 1)
  893.                         IF Remain! < 0 THEN
  894.                            CALL UpdtCalr("Sleep disconnect", 1)
  895.                            ZSubParm = -2
  896.                            ZNo = ZTrue
  897.                            ZSleepDisconnect = ZTrue
  898.                         END IF
  899.                      ELSE
  900.                         CALL Carrier
  901.                         IF ZSubParm <> -1 THEN
  902.                            ZSubParm = 0
  903.                            CALL GetCom(YY$)
  904.                         END IF
  905.                      END IF
  906.                   END IF
  907.                END IF
  908.             END IF
  909.          END IF
  910.       WEND
  911.       END SUB
  912.  
  913.       SUB GetCom (YY$)
  914.       END SUB
  915.  
  916. '*  HelpMe()
  917. '*----------------------------------------------------------------------------
  918. '*  This routine provides on-line help for the user
  919. '*
  920. '*
  921.       SUB HelpMe STATIC
  922. 2300  CALL SaveCursor(RowSave, ColSave)
  923.       CALL ClearScreen
  924.       CALL QuickTput(ZEmphasizeOff$, 0)
  925.       CALL BufFile(ZHelpPath$ + "ANSIED" + ZHelpExtension$, X)
  926.       OldColour = 0
  927.       IsBold = 99
  928.       CALL ClearScreen
  929.       FOR I = 3 TO 24
  930.          ZWorkAra$(I) = BlankLine$
  931.       NEXT I
  932.       CALL UpdateScreen
  933.       CALL MoveCursor(ColSave, RowSave)
  934.       END SUB
  935.  
  936. '*  LastParaLine()
  937. '*----------------------------------------------------------------------------
  938. '*  This routine returns ZTrue if ZOutTxt$(I) is the last line
  939. '*  in a paragraph
  940. '*
  941. '*
  942.       SUB LastParaLine (I, LastLine, Result) STATIC
  943. 2400  Result = ZFalse
  944.       IF I = LastLine OR I >= ZMaxMsgLines THEN
  945.          Result = ZTrue
  946.       ELSE
  947.          YY$ = ZOutTxt$(I)
  948.          J = INSTR(YY$, ">")
  949.          IF J = 0 THEN
  950.             J = 6
  951.          END IF
  952.          IF J < 5 THEN
  953.             Result = ZTrue
  954.          ELSEIF YY$ = BlankLine$ THEN
  955.             Result = ZTrue
  956.          ELSE
  957.             IF ZOutTxt$(I + 1) = BlankLine$ THEN
  958.                Result = ZTrue
  959.             ELSEIF LEFT$(ZOutTxt$(I + 1), 1) = " " THEN
  960.                Result = ZTrue
  961.             ELSE
  962.                K = INSTR(ZOutTxt$(I + 1), ">")
  963.                IF K <> 0 AND K < 5 THEN
  964.                   Result = ZTrue
  965.                END IF
  966.             END IF
  967.          END IF
  968.       END IF
  969.       END SUB
  970.  
  971.       SUB Line25 STATIC
  972.       END SUB
  973.  
  974. '*  MoveCursor()
  975. '*----------------------------------------------------------------------------
  976. '*  This routine moves the cursor to the position spec'd by newcol and
  977. '*  newrow and tries to do it with the minimum number of Ansi characters
  978. '*
  979. '*
  980.       SUB MoveCursor (NewRow, NewCol) STATIC
  981. 2500  IF CurrentRow = NewRow AND CurrentCol = NewCol THEN
  982.          EXIT SUB
  983.       ELSEIF NewCol = 0 AND NewRow = 0 THEN
  984.          EXIT SUB
  985.       ELSEIF NewCol = 1 AND NewRow = 1 THEN
  986.          YY$ = "f"
  987.       ELSEIF NewCol <> CurrentCol AND NewRow <> CurrentRow THEN
  988.          YY$ = "" + MID$(STR$(NewRow), 2) + ";" + MID$(STR$(NewCol), 2) + "f"
  989.       ELSE
  990.          IF CurrentCol = NewCol THEN           ' Just the row has changed
  991.             I = CurrentRow - NewRow
  992.             C$ = "A"   ' A=Up, B=Down
  993.          ELSE                                   ' Just the column changed
  994.             I = NewCol - CurrentCol
  995.             C$ = "C"   ' C=Left, D=Right
  996.          END IF
  997.          '*
  998.          '* Adjust the direction of the cursor
  999.          '*
  1000.          IF I < 0 THEN
  1001.             I = -I
  1002.             C$ = CHR$(ASC(C$) + 1)
  1003.          END IF
  1004.          YY$ = ""
  1005.          IF I > 1 THEN
  1006.             YY$ = YY$ + MID$(STR$(I), 2)
  1007.          END IF
  1008.          YY$ = YY$ + C$
  1009.       END IF
  1010.       CALL QuickTput(YY$, 0)
  1011.       ZSubParm = 0
  1012.       CurrentRow = NewRow
  1013.       CurrentCol = NewCol
  1014.       END SUB
  1015.  
  1016.       SUB NameCaps (YY$)
  1017.       END SUB
  1018.  
  1019. '*  NormalChar()
  1020. '*----------------------------------------------------------------------------
  1021. '*  This routine handles 'normal' characters entered into the message
  1022. '*
  1023. '*
  1024.       SUB NormalChar (YY$) STATIC
  1025.  
  1026. 2600  CALL SaveCursor(RowSave, ColSave)
  1027.       Index = CurrentRow + TopLine - 3
  1028.       CurrentLineBlank = (ZOutTxt$(Index) = BlankLine$)
  1029.       LML = LEN(ZOutTxt$(Index))
  1030.  
  1031.       IF CurrentCol > 79 THEN
  1032.          EXIT SUB
  1033.       END IF
  1034.  
  1035.       AtEndOfLine = ZFalse
  1036.  
  1037.       IF CurrentCol > LML THEN
  1038.          ZOutTxt$(Index) = ZOutTxt$(Index) + SPACE$(CurrentCol - LML)
  1039.          ZWorkAra$(CurrentRow) = ZWorkAra$(CurrentRow) + SPACE$(CurrentCol - LML)
  1040.          LML = LEN(ZOutTxt$(Index))
  1041.          AtEndOfLine = ZTrue
  1042.       END IF
  1043.  
  1044. 2610  IF (CurrentCol <= ZRightMargin AND AtEndOfLine) OR (CurrentCol <= ZRightMargin AND NOT InsertMode) THEN
  1045.          '*
  1046.          '* Single character changed
  1047.          '*
  1048.          MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  1049.          MID$(ZWorkAra$(CurrentRow), CurrentCol, 1) = YY$
  1050.          CALL PutScreen(YY$, YellowFore, ZTrue)
  1051.  
  1052. 2620  ELSEIF (NOT AtEndOfLine AND InsertMode AND CurrentCol <= ZRightMargin AND LML <= ZRightMargin) THEN
  1053.          '*
  1054.          '* Have to rewrite the screen from the current pos forward
  1055.          '*
  1056.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  1057.  
  1058.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  1059.  
  1060.          CALL EraseToEOL(CurrentRow, CurrentCol)
  1061.          ZZ$ = MID$(ZWorkAra$(CurrentRow), CurrentCol)
  1062.          CALL PutScreen(ZZ$, YellowFore, ZTrue)
  1063.          CALL MoveCursor(RowSave, ColSave + 1)
  1064.  
  1065. 2630  ELSE
  1066.          '*
  1067.          '* Wrap the end of the line
  1068.          '*
  1069.          IF NOT AtEndOfLine THEN
  1070.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  1071.             LML = LML + 1
  1072.          ELSE
  1073.             MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  1074.          END IF
  1075.  
  1076.          CALL FindWrap(ZOutTxt$(Index), I)
  1077.          IF I = 0 OR I = 1 THEN
  1078.             I = ZRightMargin
  1079.          END IF
  1080.  
  1081.          ZZ$ = MID$(ZOutTxt$(Index), (I + 1))
  1082.          CALL RightTrim(ZZ$)
  1083.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), I)
  1084.          ' add to the beginning of a new line
  1085.          IF Index <= 98 THEN
  1086.             Index = Index + 1
  1087.          END IF
  1088.          FOR J = 98 TO Index STEP -1
  1089.             ZOutTxt$(J + 1) = ZOutTxt$(J)
  1090.          NEXT J
  1091.          ZOutTxt$(Index) = ZZ$
  1092.  
  1093.          CALL EraseToEOL(CurrentRow, I + 1)        ' do the "easy" line
  1094.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  1095.  
  1096.          CALL UpdateScreen
  1097.          IF (ColSave > I) THEN
  1098.             NewCol = ColSave - I + 1
  1099.             IF RowSave <> 24 THEN
  1100.                CALL MoveCursor(RowSave + 1, NewCol)
  1101.             ELSE
  1102.                CALL MoveCursor(RowSave, NewCol)
  1103.                CALL Ungetch(LineDownKey)
  1104.             END IF
  1105.          ELSE
  1106.             CALL MoveCursor(RowSave, ColSave + 1)
  1107.          END IF
  1108.       END IF
  1109.  
  1110.       END SUB
  1111.  
  1112. '*  PutScreen()
  1113. '*----------------------------------------------------------------------------
  1114. '* This routine writes YY$ to the user in the color and
  1115. '* intensity specified
  1116. '*
  1117. '*
  1118.       SUB PutScreen (YY$, Colour, Bold) STATIC
  1119. 2800  ZZ$ = ""
  1120.       IF Colour <> 99 THEN
  1121.          IF (Colour <> OldColour) OR (Bold <> IsBold) THEN
  1122.             ZZ$ = ""
  1123.             IF Bold <> IsBold THEN
  1124.                IF Bold THEN
  1125.                   ZZ$ = ZZ$ + "1;"
  1126.                   IsBold = ZTrue
  1127.                ELSE
  1128.                   ZZ$ = ZZ$ + "0;"
  1129.                   IsBold = ZFalse
  1130.                END IF
  1131.             END IF
  1132.             ZZ$ = ZZ$ + MID$(STR$(Colour), 2)
  1133.             ZZ$ = ZZ$ + "m"
  1134.          END IF
  1135.       END IF
  1136.       ZOutTxt$ = ZZ$ + YY$
  1137.       IF ZLocalUser THEN
  1138.          CALL QuickTput(ZOutTxt$, 0)
  1139.       ELSE
  1140.          ZSubParm = 4
  1141.          CALL Tput
  1142.          ZSubParm = 0
  1143.       END IF
  1144.       IF INSTR(YY$, "") = 0 THEN
  1145.          CurrentCol = CurrentCol + LEN(YY$)
  1146.          IF CurrentCol > 80 THEN
  1147.             CurrentCol = 0
  1148.             CurrentRow = 0
  1149.          END IF
  1150.       ELSE
  1151.          CurrentRow = 0
  1152.          CurrentCol = 0
  1153.       END IF
  1154.       OldColour = Colour
  1155.       Colour = 99
  1156.       END SUB
  1157.  
  1158.       SUB QuickTput (YY$, NumReturns) STATIC
  1159.       OPEN "Cons:" FOR OUTPUT AS #3
  1160.       PRINT #3, YY$;
  1161.       FOR I = 1 TO NumReturns
  1162.          PRINT #3,
  1163.       NEXT
  1164.       CLOSE 3
  1165.       END SUB
  1166.  
  1167.       SUB QuickTput1 (YY$) STATIC
  1168.       CALL QuickTput(YY$, 1)
  1169.       END SUB
  1170.  
  1171. '*  ReformText()
  1172. '*----------------------------------------------------------------------------
  1173. '*  This routine reflows the text to the current margins.  Optionally,
  1174. '*  it right justifies all lines by adding "soft spaces"
  1175. '*
  1176. '*
  1177.       SUB ReformText (Justify%) STATIC
  1178.  
  1179. 2900  DIM SpacePlace(80)
  1180.  
  1181.       CALL ClearMainMenu
  1182.       CALL PutScreen("Reformatting... Please Wait.", WhiteFore, ZTrue)
  1183.  
  1184.       LastLine = 1
  1185.       FOR I = ZMaxMsgLines TO 1 STEP -1
  1186.          IF ZOutTxt$(I) <> BlankLine$ THEN
  1187.             LastLine = I
  1188.             EXIT FOR
  1189.          END IF
  1190.       NEXT
  1191.  
  1192.       I = MsgLockLines + 1   ' Read index
  1193.       J = MsgLockLines + 1   ' Write index
  1194.  
  1195.       '*
  1196.       '* Reflow the text to the maximum on a line
  1197.       '*
  1198.       DO WHILE I <= LastLine
  1199.          ZOutTxt$ = ""
  1200.          DO WHILE 1
  1201.             YY$ = ZOutTxt$(I)
  1202.             CALL UnString(YY$, SoftSpace$)
  1203.             IF ZOutTxt$ <> "" AND RIGHT$(ZOutTxt$, 1) <> " " THEN
  1204.                ZOutTxt$ = ZOutTxt$ + " "
  1205.             END IF
  1206.             ZOutTxt$ = ZOutTxt$ + YY$
  1207.             CALL LastParaLine(I, LastLine, Z)
  1208.             IF LEN(ZOutTxt$) > ZRightMargin OR Z THEN
  1209.                IF LEN(ZOutTxt$) > ZRightMargin THEN
  1210.                   CALL FindWrap(LEFT$(ZOutTxt$, ZRightMargin + 1), K)
  1211.                   IF K = 0 OR K = 1 THEN K = ZRightMargin
  1212.                   ZOutTxt$(J) = LEFT$(ZOutTxt$, K)
  1213.                   IF Z THEN
  1214.                      ' Go to the next paragraph
  1215.                      ZOutTxt$(J + 1) = MID$(ZOutTxt$, K + 1)
  1216.                      J = J + 2
  1217.                      I = I + 1
  1218.                      EXIT DO
  1219.                   ELSE
  1220.                      ZOutTxt$(I) = MID$(ZOutTxt$, K + 1)
  1221.                      J = J + 1
  1222.                      EXIT DO
  1223.                   END IF
  1224.                ELSE          ' Z is ZTrue
  1225.                   ZOutTxt$(J) = ZOutTxt$
  1226.                   J = J + 1
  1227.                   I = I + 1
  1228.                   EXIT DO
  1229.                END IF
  1230.             ELSE
  1231.                I = I + 1
  1232.             END IF
  1233.          LOOP
  1234.       LOOP
  1235.  
  1236.       FOR I = J TO 99
  1237.          ZOutTxt$(I) = BlankLine$
  1238.       NEXT
  1239.  
  1240.       LastLine = J - 1
  1241.  
  1242.       '*
  1243.       '* Space out the text on each line
  1244.       '*
  1245.       IF Justify% THEN
  1246.          FOR I = MsgLockLines + 1 TO LastLine
  1247.             CALL LastParaLine(I, LastLine, Z)
  1248.             IF Z THEN
  1249.             ELSE
  1250.                ZOutTxt$ = ZOutTxt$(I)
  1251.                ZOutTxt$ = RTRIM$(ZOutTxt$)
  1252.                '*
  1253.                '* Skip leading spaces on the line
  1254.                '*
  1255.                J = -1
  1256.                FOR K = 1 TO LEN(ZOutTxt$)
  1257.                   IF MID$(ZOutTxt$, K, 1) <> " " THEN
  1258.                      J = K
  1259.                      EXIT FOR
  1260.                   END IF
  1261.                NEXT
  1262.                IF J <> -1 THEN
  1263.                   '*
  1264.                   '* Find out all of the possible places to put spaces
  1265.                   '*
  1266.                   L = 0
  1267.                   M = INSTR(J, ZOutTxt$, " ")
  1268.                   WHILE M <> 0
  1269.                      L = L + 1
  1270.                      SpacePlace(L) = M
  1271.                      M = INSTR(M + 1, ZOutTxt$, " ")
  1272.                   WEND
  1273.                   IF L <> 0 THEN
  1274.                      '*
  1275.                      '* Space out the line.  First add a space to the
  1276.                      '* start of the line, then add to the end.
  1277.                      '*
  1278.                      SpacesToAdd = ZRightMargin - LEN(ZOutTxt$)
  1279.                      M = 1
  1280.                      N = L
  1281.                      DoM = ZTrue
  1282.                      WHILE SpacesToAdd <> 0
  1283.                         IF DoM THEN
  1284.                            Place = SpacePlace(M)
  1285.                            M = M + 1
  1286.                         ELSE
  1287.                            Place = SpacePlace(N)
  1288.                            N = N - 1
  1289.                         END IF
  1290.                         DoM = NOT DoM
  1291.                         ZOutTxt$(I) = LEFT$(ZOutTxt$(I), Place) + SoftSpace$ + MID$(ZOutTxt$(I), Place + 1)
  1292.                         SpacesToAdd = SpacesToAdd - 1
  1293.                         FOR P = 1 TO L
  1294.                            IF SpacePlace(P) > Place THEN
  1295.                               SpacePlace(P) = SpacePlace(P) + 1
  1296.                            END IF
  1297.                         NEXT
  1298.                         IF M = N THEN
  1299.                            M = 1
  1300.                            N = L
  1301.                         END IF
  1302.                      WEND
  1303.                   END IF
  1304.                END IF
  1305.             END IF
  1306.          NEXT
  1307.       END IF
  1308.  
  1309.       CALL UpdateScreen
  1310.  
  1311.       END SUB
  1312.  
  1313. '*  RightTrim()
  1314. '*----------------------------------------------------------------------------
  1315. '*   Removes soft spaces from a string
  1316. '*
  1317. '*
  1318.       SUB RightTrim (YY$) STATIC
  1319. 3000  FOR I = LEN(YY$) TO 1 STEP -1
  1320.          IF MID$(YY$, I, 1) <> SoftSpace$ THEN
  1321.             YY$ = LEFT$(YY$, I)
  1322.             EXIT SUB
  1323.          END IF
  1324.       NEXT I
  1325.       YY$ = ""
  1326.       END SUB
  1327.  
  1328. '*  SaveCursor()
  1329. '*----------------------------------------------------------------------------
  1330. '*  This routine saves the current cursor position
  1331. '*
  1332. '*
  1333.       SUB SaveCursor (Row%, Col%) STATIC
  1334.       Row% = CurrentRow
  1335.       Col% = CurrentCol
  1336.       END SUB
  1337.  
  1338.       SUB Tput STATIC
  1339.       CALL QuickTput(ZOutTxt$, 0)
  1340.       END SUB
  1341.  
  1342. '*  UnGetch()
  1343. '*----------------------------------------------------------------------------
  1344. '*   Puts a key in the beginning of the keyboard buffer
  1345. '*
  1346. '*
  1347.       SUB Ungetch (X) STATIC
  1348.       ZCommportStack$ = CHR$(X) + ZCommportStack$
  1349.       END SUB
  1350.  
  1351. '*  UnString()
  1352. '*----------------------------------------------------------------------------
  1353. '*  Removes one string from another
  1354. '*
  1355. '*
  1356.       SUB UnString (WasL$, BadString$) STATIC
  1357.       WasI = INSTR(WasL$, BadString$)
  1358.       WHILE WasI <> 0
  1359.          WasL$ = LEFT$(WasL$, WasI - 1) + MID$(WasL$, WasI + LEN(BadString$))
  1360.          WasI = INSTR(WasL$, BadString$)
  1361.       WEND
  1362.       END SUB
  1363.  
  1364. '*  UpdateScreen()
  1365. '*----------------------------------------------------------------------------
  1366. '*  This is one of the most important routines  It compares the arrays
  1367. '*  ZOutTxt$ and ZWorkAra$ and only sends the user the DIFFERENCE between the
  1368. '*  two within the viewing area  In this way all processing can be done on
  1369. '*  ZOutTxt$ and then the screen is updated to reflect the changes. After the
  1370. '*  users screen is updated, ZWorkAra$ is changed to reflect what should be
  1371. '*  on the users' screen The cursor is restored to its original position
  1372. '*
  1373. '*
  1374.       SUB UpdateScreen STATIC
  1375. 3100  CALL SaveCursor(RowSave, ColSave)
  1376.       FOR I = 3 TO 24
  1377.          Index = I + TopLine - 3
  1378.          ScreenLine$ = ZWorkAra$(I)
  1379.          MessageLine$ = ZOutTxt$(Index)
  1380.          LML = LEN(MessageLine$)
  1381.          IF Index = ZMaxMsgLines + 1 THEN
  1382.             CALL EraseToEOL(I, 1)
  1383.             CALL MoveCursor(I, 1)
  1384.             CALL PutScreen("[* End of Message *]", CyanFore, ZFalse)
  1385.             ZWorkAra$(I) = CHR$(EndKey)
  1386.          ELSEIF Index > ZMaxMsgLines + 1 THEN
  1387.             IF ScreenLine$ <> BlankLine$ THEN
  1388.                CALL EraseToEOL(I, 1)
  1389.                ZWorkAra$(I) = BlankLine$
  1390.             END IF
  1391.          ELSEIF MessageLine$ = ScreenLine$ THEN
  1392.             '*
  1393.             '* Screen = What's in message buffer
  1394.             '*
  1395.          ELSEIF MessageLine$ = BlankLine$ OR MessageLine$ = SPACE$(LML) THEN
  1396.             CALL EraseToEOL(I, 1)
  1397.             ZWorkAra$(I) = MessageLine$
  1398.          ELSE
  1399.             CALL MoveCursor(I, 1)
  1400.             YY$ = MessageLine$
  1401.             CALL PutScreen(YY$, YellowFore, ZTrue)
  1402.             CALL EraseToEOL(CurrentRow, CurrentCol)
  1403.             ZWorkAra$(I) = ZOutTxt$(Index)
  1404.          END IF
  1405.       NEXT I
  1406.       CALL MoveCursor(RowSave, ColSave)
  1407.       END SUB
  1408.  
  1409. '*  UpdateStatusLine()
  1410. '*-----------------------------------------------------------------------------
  1411. '*  Rewrites the status line on screen line(s) 1 and 2
  1412. '*
  1413. '*    Input:  How% = 1   - Rewrite both lines
  1414. '*            How% = 2   - Just rewrite top line
  1415. '*
  1416.       SUB UpdateStatusLine (How%) STATIC
  1417. 3200  YY$ = "ANSIED " + Version$ + " by Tom Collins                       * Press ESC Twice for Menu *"
  1418.       YY$ = YY$ + SPACE$(79 - LEN(YY$))
  1419.       CALL MoveCursor(1, 1)
  1420.       CALL PutScreen(YY$, BlueFore, ZTrue)
  1421. 3210  IF How% = 1 THEN
  1422.          YY$ = CHR$(205) + " To: " + MsgTo$ + " " + STRING$(3, CHR$(205)) + " Subject: " + MsgSubj$ + " " + STRING$(3, CHR$(205))
  1423.          InsOvwPosition = LEN(YY$)
  1424.          IF InsertMode THEN
  1425.             YY$ = YY$ + " Insert " + STRING$(3, CHR$(205))
  1426.          ELSE
  1427.             YY$ = YY$ + " Overwrite "
  1428.          END IF
  1429.          YY$ = YY$ + STRING$(79 - LEN(YY$), CHR$(205))
  1430.          I = 1
  1431.          CALL MoveCursor(2, I)
  1432.          CALL PutScreen(YY$, WhiteFore, ZFalse)
  1433.       END IF
  1434.       END SUB
  1435.  
  1436.       SUB UpdtCalr (YY$, Z) STATIC
  1437.       END SUB
  1438.  
  1439.